﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Globalization;

namespace SmartMathLibrary.Management.Performance
{
    /// <summary>
    /// Defines the significant properties of a processor.
    /// </summary>
    public enum ProcessorProperty
    {
        /// <summary>
        /// The AddressWidth property of the processor.
        /// </summary>
        AddressWidth,
        /// <summary>
        /// The Architecture property of the processor.
        /// </summary>
        Architecture,
        /// <summary>
        /// The Availability property of the processor.
        /// </summary>
        Availability,
        /// <summary>
        /// The Caption property of the processor.
        /// </summary>
        Caption,
        /// <summary>
        /// The ConfigManagerErrorCode property of the processor.
        /// </summary>
        ConfigManagerErrorCode,
        /// <summary>
        /// The ConfigManagerUserConfig property of the processor.
        /// </summary>
        ConfigManagerUserConfig,
        /// <summary>
        /// The CpuStatus property of the processor.
        /// </summary>
        CpuStatus,
        /// <summary>
        /// The CreationClassName property of the processor.
        /// </summary>
        CreationClassName,
        /// <summary>
        /// The CurrentClockSpeed property of the processor.
        /// </summary>
        CurrentClockSpeed,
        /// <summary>
        /// The CurrentVoltage property of the processor.
        /// </summary>
        CurrentVoltage,
        /// <summary>
        /// The DataWidth property of the processor.
        /// </summary>
        DataWidth,
        /// <summary>
        /// The DeviceID property of the processor.
        /// </summary>
        DeviceID,
        /// <summary>
        /// The ErrorCleared property of the processor.
        /// </summary>
        ErrorCleared,
        /// <summary>
        /// The ErrorDescription property of the processor.
        /// </summary>
        ErrorDescription,
        /// <summary>
        /// The ExtClock property of the processor.
        /// </summary>
        ExtClock,
        /// <summary>
        /// The Family property of the processor.
        /// </summary>
        Family,
        /// <summary>
        /// The L2CacheSize property of the processor.
        /// </summary>
        L2CacheSize,
        /// <summary>
        /// The L2CacheSpeed property of the processor.
        /// </summary>
        L2CacheSpeed,
        /// <summary>
        /// The L3CacheSize property of the processor.
        /// </summary>
        L3CacheSize,
        /// <summary>
        /// The L3CacheSpeed property of the processor.
        /// </summary>
        L3CacheSpeed,
        /// <summary>
        /// The LastErrorCode property of the processor.
        /// </summary>
        LastErrorCode,
        /// <summary>
        /// The Level property of the processor.
        /// </summary>
        Level,
        /// <summary>
        /// The LoadPercentage property of the processor.
        /// </summary>
        LoadPercentage,
        /// <summary>
        /// The Manufacturer property of the processor.
        /// </summary>
        Manufacturer,
        /// <summary>
        /// The MaxClockSpeed property of the processor.
        /// </summary>
        MaxClockSpeed,
        /// <summary>
        /// The Name property of the processor.
        /// </summary>
        Name,
        /// <summary>
        /// The NumberOfCores property of the processor.
        /// </summary>
        NumberOfCores,
        /// <summary>
        /// The NumberOfLogicalProcessors property of the processor.
        /// </summary>
        NumberOfLogicalProcessors,
        /// <summary>
        /// The OtherFamilyDescription property of the processor.
        /// </summary>
        OtherFamilyDescription,
        /// <summary>
        /// The PNPDeviceID property of the processor.
        /// </summary>
        PNPDeviceID,
        /// <summary>
        /// The PowerManagementSupported property of the processor.
        /// </summary>
        PowerManagementSupported,
        /// <summary>
        /// The ProcessorType property of the processor.
        /// </summary>
        ProcessorType,
        /// <summary>
        /// The Role property of the processor.
        /// </summary>
        Role,
        /// <summary>
        /// The SocketDesignation property of the processor.
        /// </summary>
        SocketDesignation,
        /// <summary>
        /// The Status property of the processor.
        /// </summary>
        Status,
        /// <summary>
        /// The StatusInfo property of the processor.
        /// </summary>
        StatusInfo,
        /// <summary>
        /// The Stepping property of the processor.
        /// </summary>
        Stepping,
        /// <summary>
        /// The SystemCreationClassName property of the processor.
        /// </summary>
        SystemCreationClassName,
        /// <summary>
        /// The SystemName property of the processor.
        /// </summary>
        SystemName,
        /// <summary>
        /// The UniqueId property of the processor.
        /// </summary>
        UniqueId,
        /// <summary>
        /// The UpgradeMethod property of the processor.
        /// </summary>
        UpgradeMethod,
        /// <summary>
        /// The Version property of the processor.
        /// </summary>
        Version,
        /// <summary>
        /// The VoltageCaps property of the processor.
        /// </summary>
        VoltageCaps
    }

    /// <summary>
    /// This class provides a gateway to information of the current processor,
    /// which includes the running system.
    /// </summary>
    [Serializable]
    public static class ProcessorInformationProvider
    {
        /// <summary>
        /// Collects the significant information of the current processor.
        /// </summary>
        /// <returns>The significant information of the current processor.</returns>
        public static ProcessorInformation[] CollectInformations()
        {
            int i = 0;
            ManagementObjectSearcher searcher = new ManagementObjectSearcher
                ("root\\CIMV2", "SELECT * FROM Win32_Processor");

            ProcessorInformation[] informations = new ProcessorInformation[searcher.Get().Count];

            try
            {
                foreach (ManagementObject queryObj in searcher.Get())
                {
                    informations[i] = new ProcessorInformation();

                    if (queryObj["AddressWidth"] != null)
                    {
                        informations[i].AddressWidth = UInt16.Parse(queryObj["AddressWidth"].ToString(),
                                                                    CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Architecture"] != null)
                    {
                        informations[i].Architecture = UInt16.Parse(queryObj["Architecture"].ToString(),
                                                                    CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Availability"] != null)
                    {
                        informations[i].Availability = UInt16.Parse(queryObj["Availability"].ToString(),
                                                                    CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Caption"] != null)
                    {
                        informations[i].Caption = queryObj["Caption"].ToString();
                    }

                    if (queryObj["ConfigManagerErrorCode"] != null)
                    {
                        informations[i].ConfigManagerErrorCode =
                            UInt32.Parse(queryObj["ConfigManagerErrorCode"].ToString(), CultureInfo.CurrentCulture);
                    }

                    if (queryObj["ConfigManagerUserConfig"] != null)
                    {
                        informations[i].ConfigManagerUserConfig =
                            Boolean.Parse(queryObj["ConfigManagerUserConfig"].ToString());
                    }

                    if (queryObj["CpuStatus"] != null)
                    {
                        informations[i].CpuStatus = UInt16.Parse(queryObj["CpuStatus"].ToString(),
                                                                 CultureInfo.CurrentCulture);
                    }

                    if (queryObj["CreationClassName"] != null)
                    {
                        informations[i].CreationClassName = queryObj["CreationClassName"].ToString();
                    }

                    if (queryObj["CurrentClockSpeed"] != null)
                    {
                        informations[i].CurrentClockSpeed = UInt32.Parse(queryObj["CurrentClockSpeed"].ToString(),
                                                                         CultureInfo.CurrentCulture);
                    }

                    if (queryObj["CurrentVoltage"] != null)
                    {
                        informations[i].CurrentVoltage = UInt16.Parse(queryObj["CurrentVoltage"].ToString(),
                                                                      CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Description"] != null)
                    {
                        informations[i].Description = queryObj["Description"].ToString();
                    }

                    if (queryObj["DeviceID"] != null)
                    {
                        informations[i].DeviceID = queryObj["DeviceID"].ToString();
                    }

                    if (queryObj["ErrorCleared"] != null)
                    {
                        informations[i].ErrorCleared = Boolean.Parse(queryObj["ErrorCleared"].ToString());
                    }

                    if (queryObj["ErrorDescription"] != null)
                    {
                        informations[i].ErrorDescription = queryObj["ErrorDescription"].ToString();
                    }

                    if (queryObj["ExtClock"] != null)
                    {
                        informations[i].ExtClock = UInt32.Parse(queryObj["ExtClock"].ToString(),
                                                                CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Family"] != null)
                    {
                        informations[i].Family = UInt16.Parse(queryObj["Family"].ToString(), CultureInfo.CurrentCulture);
                    }

                    if (queryObj["L2CacheSize"] != null)
                    {
                        informations[i].L2CacheSize = UInt32.Parse(queryObj["L2CacheSize"].ToString(),
                                                                   CultureInfo.CurrentCulture);
                    }

                    if (queryObj["L2CacheSpeed"] != null)
                    {
                        informations[i].L2CacheSpeed = UInt32.Parse(queryObj["L2CacheSpeed"].ToString(),
                                                                    CultureInfo.CurrentCulture);
                    }

                    if (queryObj["LastErrorCode"] != null)
                    {
                        informations[i].LastErrorCode = UInt32.Parse(queryObj["LastErrorCode"].ToString(),
                                                                     CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Level"] != null)
                    {
                        informations[i].Level = UInt16.Parse(queryObj["Level"].ToString(), CultureInfo.CurrentCulture);
                    }

                    if (queryObj["LoadPercentage"] != null)
                    {
                        informations[i].LoadPercentage = UInt16.Parse(queryObj["LoadPercentage"].ToString(),
                                                                      CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Manufacturer"] != null)
                    {
                        informations[i].Manufacturer = queryObj["Manufacturer"].ToString();
                    }

                    if (queryObj["MaxClockSpeed"] != null)
                    {
                        informations[i].MaxClockSpeed = UInt32.Parse(queryObj["MaxClockSpeed"].ToString(),
                                                                     CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Name"] != null)
                    {
                        informations[i].Name = queryObj["Name"].ToString();
                    }

                    if (queryObj["OtherFamilyDescription"] != null)
                    {
                        informations[i].OtherFamilyDescription = queryObj["OtherFamilyDescription"].ToString();
                    }

                    if (queryObj["PNPDeviceID"] != null)
                    {
                        informations[i].PNPDeviceID = queryObj["PNPDeviceID"].ToString();
                    }

                    if (queryObj["PowerManagementSupported"] != null)
                    {
                        informations[i].PowerManagementSupported =
                            Boolean.Parse(queryObj["PowerManagementSupported"].ToString());
                    }

                    if (queryObj["ProcessorId"] != null)
                    {
                        informations[i].ProcessorId = queryObj["ProcessorId"].ToString();
                    }

                    if (queryObj["ProcessorType"] != null)
                    {
                        informations[i].ProcessorType = UInt16.Parse(queryObj["ProcessorType"].ToString(),
                                                                     CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Revision"] != null)
                    {
                        informations[i].Revision = UInt16.Parse(queryObj["Revision"].ToString(),
                                                                CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Role"] != null)
                    {
                        informations[i].Role = queryObj["Role"].ToString();
                    }

                    if (queryObj["SocketDesignation"] != null)
                    {
                        informations[i].SocketDesignation = queryObj["SocketDesignation"].ToString();
                    }

                    if (queryObj["Status"] != null)
                    {
                        informations[i].Status = queryObj["Status"].ToString();
                    }

                    if (queryObj["StatusInfo"] != null)
                    {
                        informations[i].StatusInfo = UInt16.Parse(queryObj["StatusInfo"].ToString(),
                                                                  CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Stepping"] != null)
                    {
                        informations[i].Stepping = queryObj["Stepping"].ToString();
                    }

                    if (queryObj["SystemCreationClassName"] != null)
                    {
                        informations[i].SystemCreationClassName = queryObj["SystemCreationClassName"].ToString();
                    }

                    if (queryObj["SystemName"] != null)
                    {
                        informations[i].SystemName = queryObj["SystemName"].ToString();
                    }

                    if (queryObj["UniqueId"] != null)
                    {
                        informations[i].UniqueId = queryObj["UniqueId"].ToString();
                    }

                    if (queryObj["UpgradeMethod"] != null)
                    {
                        informations[i].UpgradeMethod = UInt16.Parse(queryObj["UpgradeMethod"].ToString(),
                                                                     CultureInfo.CurrentCulture);
                    }

                    if (queryObj["Version"] != null)
                    {
                        informations[i].Version = queryObj["Version"].ToString();
                    }

                    if (queryObj["VoltageCaps"] != null)
                    {
                        informations[i].VoltageCaps = UInt32.Parse(queryObj["VoltageCaps"].ToString(),
                                                                   CultureInfo.CurrentCulture);
                    }

                    i++;
                }
            }
            catch
            {
                throw new InformationNotFoundException("Cannot find the specified information.");
            }

            return informations;
        }

        /// <summary>
        /// Collects a special information of the processor.
        /// </summary>
        /// <param name="property">The special information property.</param>
        /// <returns>The special information of the processor.</returns>
        public static Object[] CollectSpecialInformation(ProcessorProperty property)
        {
            int i = 0;
            ManagementObjectSearcher searcher = new ManagementObjectSearcher
                ("root\\CIMV2", "SELECT * FROM Win32_Processor");
            Object[] informations = new Object[searcher.Get().Count];

            try
            {
                foreach (ManagementObject queryObj in searcher.Get())
                {
                    informations[i] = queryObj[property.ToString()];
                    i++;
                }
            }
            catch
            {
                throw new InformationNotFoundException("Cannot find the specified information.");
            }

            return informations;
        }
    }
}